{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- C++11～C++23 Lambda 演进速览\n",
    "\n",
    "| 标准  | 重要新增能力                                                 | 主要遗留缺陷/限制                                            |\n",
    "| ----- | ------------------------------------------------------------ | ------------------------------------------------------------ |\n",
    "| C++11 | 首次引入 lambda 表达式、捕获列表、`mutable`/`noexcept`、可转换为无捕获函数指针 | 不能移动捕获、不能泛型参数、闭包类型不可复制/赋值、类型难以命名 |\n",
    "| C++14 | 泛型 lambda（`auto` 参数）、初始化捕获（含移动捕获）、返回值自动推断 | 仍需 `mutable` 才能修改捕获副本、闭包类型仍匿名、`constexpr` 支持有限 |\n",
    "| C++17 | `constexpr` lambda、默认 `constexpr` 调用运算符、捕获 `*this`、lambda 可用于常量上下文 | `*this` 捕获会复制整个对象、仍缺定位命名闭包、无模板头       |\n",
    "| C++20 | lambda 模板形参（`[]<typename T>`）、`consteval`/`constinit`/`constexpr` 支持完善、可在 `requires` 表达式中使用 | 闭包类型依然匿名、无显式对象参数（需 C++23 deducing this，lambda 不适用） |\n",
    "| C++23 | 标准库配套（如 `std::move_only_function`）改善可存储性；lambda 更好地与 `constexpr`/并发库协作 | 语言层面几乎无新语法；闭包不能默认比较/赋值、捕获与生命周期管理仍需谨慎 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 捕获列表 | 含义                           | 特点                                                         | 典型用途                                                     |\n",
    "| -------- | ------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |\n",
    "| `[]`     | 不捕获任何外部变量             | 只能使用参数或全局/静态对象；可隐式转为函数指针              | 纯函数式 lambda，或不依赖外部状态的回调                      |\n",
    "| `[=]`    | **按值**捕获外部作用域中的变量 | 每个被使用的变量都会复制进闭包；默认只读，需 `mutable` 才能改副本；若变量不可复制则报错 | 需要在 lambda 内保留调用时的值快照；跨线程、延迟执行时避免悬挂引用 |\n",
    "| `[&]`    | **按引用**捕获外部变量         | 不复制，直接引用外部变量；可读写原变量；要求外部变量在闭包存活期内仍有效 | lambda 内需要修改外部状态，或对大型对象避免拷贝              |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# C++11：lambda 初登场\n",
    "\n",
    "**要点**\n",
    "\n",
    "- 语法：`[捕获](参数) mutable? noexcept? -> 返回 { ... }`\n",
    "- 默认按值捕获的变量只读；`mutable` 才能修改副本。\n",
    "- 无捕获 lambda 可隐式转换为函数指针。\n",
    "\n",
    "**缺陷**\n",
    "\n",
    "- 不能在捕获列表内写初始化（如移动捕获）。\n",
    "- 参数类型必须显式书写，缺乏泛型能力。\n",
    "- 闭包类型匿名、不可赋值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "\n",
    "int main() {\n",
    "    int factor = 2;\n",
    "    auto scale = [factor](int x) { return factor * x; };\n",
    "\n",
    "    std::cout << scale(21) << '\\n'; // 42\n",
    "\n",
    "    // C++11 不支持：auto move_lambda = [ptr = std::move(unique_ptr)] { ... };\n",
    "    // 需要 C++14 初始化捕获。\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# C++14：泛型与初始化捕获\n",
    "\n",
    "**要点**\n",
    "\n",
    "- 泛型 lambda：`auto` 形参自动推断。\n",
    "- 初始化捕获：`[value = std::move(v)]` 支持移动捕获或任意表达式初始化。\n",
    "- 返回类型自动推断更友好（多行返回一致时可不写 `->`）。\n",
    "\n",
    "**缺陷**\n",
    "\n",
    "- 捕获到的副本仍默认只读；修改需 `mutable`。\n",
    "- 仍无直接命名闭包类型的手段。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "#include <memory>\n",
    "\n",
    "int main() {\n",
    "    auto printer = [](const auto& value) {\n",
    "        std::cout << value << '\\n';\n",
    "    };\n",
    "    printer(\"generic lambda works\");\n",
    "    printer(42);\n",
    "\n",
    "    auto make_counter = [count = 0]() mutable {\n",
    "        return ++count;\n",
    "    };\n",
    "    std::cout << make_counter() << '\\n'; // 1\n",
    "    std::cout << make_counter() << '\\n'; // 2\n",
    "\n",
    "    auto unique = std::make_unique<int>(99);\n",
    "    auto keep = [ptr = std::move(unique)] { return *ptr; };\n",
    "    std::cout << keep() << '\\n'; // 99\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# C++17：constexpr 与捕获 `*this`\n",
    "\n",
    "**要点**\n",
    "\n",
    "- `constexpr` lambda：可用于编译期求值，且若可能，`operator()` 默认即 `constexpr`。\n",
    "- 捕获 `*this`：`[*this]` 复制当前对象，适合值语义闭包。\n",
    "- lambda 可用于模板参数、`constexpr` 容器、折叠等。\n",
    "\n",
    "**缺陷**\n",
    "\n",
    "- `[*this]` 会复制整个对象，可能昂贵或意外；若需引用仍要 `[this]`。\n",
    "- 闭包类型仍不可复制赋值，使用容器时受限。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <array>\n",
    "#include <iostream>\n",
    "\n",
    "constexpr auto square = [](int n) { return n * n; };\n",
    "static_assert(square(5) == 25);\n",
    "\n",
    "struct Point {\n",
    "    int x{}, y{};\n",
    "    auto binder() const {\n",
    "        return [*this]() { return x + y; }; // C++17 复制整个 Point\n",
    "    }\n",
    "};\n",
    "\n",
    "int main() {\n",
    "    auto sum = square(7); // 49\n",
    "    std::cout << sum << '\\n';\n",
    "\n",
    "    Point p{3, 4};\n",
    "    auto f = p.binder();\n",
    "    std::cout << f() << '\\n'; // 7\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# C++20：模板 lambda 与 `consteval`\n",
    "\n",
    "**要点**\n",
    "\n",
    "- 可在 `[]` 后写模板头：`[]<typename T>(T value){ ... }`，自定义概念+约束组合更灵活。\n",
    "- lambda 可标记 `consteval` / `constexpr` / `constinit`，与编译期评估无缝衔接。\n",
    "- 与 `requires`、`concepts`、`constexpr` 容器配合增强泛型能力。\n",
    "\n",
    "**缺陷**\n",
    "\n",
    "- 闭包类型依旧匿名且不可复制赋值，想要在标准容器中保存需 `std::function` 或自写包装。\n",
    "- 无法显式控制隐式对象参数（`this`）推导。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <concepts>\n",
    "#include <iostream>\n",
    "\n",
    "int main() {\n",
    "    auto classify = []<typename T>(T value) {\n",
    "        if constexpr (std::integral<T>) {\n",
    "            return value % 2 == 0 ? \"even int\" : \"odd int\";\n",
    "        } else if constexpr (std::floating_point<T>) {\n",
    "            return \"floating point\";\n",
    "        } else {\n",
    "            return \"unknown\";\n",
    "        }\n",
    "    };\n",
    "\n",
    "    std::cout << classify(42) << '\\n';     // even int\n",
    "    std::cout << classify(3.14) << '\\n';   // floating point\n",
    "\n",
    "    auto immediate = [] consteval { return 2020; };\n",
    "    constexpr int year = immediate(); // 编译期常量\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# C++23：生态强化，语法趋于稳定"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**要点**\n",
    "\n",
    "- 语言层面对 lambda 的新增不多，重心在库支持：\n",
    "  - `std::move_only_function` 可存储捕获了 move-only 资源的闭包。\n",
    "  - 结合 `constexpr` 容器、`ranges`、`views::zip` 等新组件更易写函数式代码。\n",
    "- 新标准库算法 (`std::ranges` 扩展) 更依赖 lambda，语法协同更佳。\n",
    "\n",
    "**缺陷**\n",
    "\n",
    "- 闭包仍未提供内建比较/赋值，类型匿名导致模板接口需要 auto/模板参数。\n",
    "- 捕获生命周期与线程安全问题仍需显式管理。\n",
    "- 仍无法直接把 lambda 当作 non-type template parameter（除非加 `constexpr` + `auto` 变量包装）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <functional>\n",
    "#include <iostream>\n",
    "#include <memory>\n",
    "\n",
    "std::move_only_function<int()> make_worker() {\n",
    "    auto resource = std::make_unique<int>(123);\n",
    "    return std::move_only_function<int()>(\n",
    "        [ptr = std::move(resource)] { return *ptr; }\n",
    "    );\n",
    "}\n",
    "\n",
    "int main() {\n",
    "    auto worker = make_worker();\n",
    "    std::cout << worker() << '\\n'; // 123\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> **注意**：`std::move_only_function` 出自 C++23 `<functional>`，用于保存 move-only 闭包（`std::function` 仍要求可复制）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 常见遗留痛点提示\n",
    "\n",
    "- **闭包类型匿名**：无法命名，若需跨接口传递，通常用 `auto`、模板或包装类（`std::function`/`move_only_function`/`function_ref` 提案）。\n",
    "- **捕获生命周期**：按值捕获副本独立存在；按引用捕获需确保原对象生命周期长于闭包。\n",
    "- **可修改捕获**：默认 `operator()` 为 `const`，修改捕获需 `mutable`。\n",
    "- **并发环境**：捕获可变状态时注意同步，尤其是按引用捕获的共享变量。\n",
    "- **异常与 noexcept**：默认继承 `noexcept(false)`；可显式添加 `noexcept` 避免意外传播。\n",
    "\n",
    "通过以上时间线可以快速理解 lambda 从 C++11 初始设计到 C++23 生态完善的演进，同时在使用时对现存限制保持警惕。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "name": "C++17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
